/**
 * 测试父亲对孩子发射一个SIGINI信号，并回收其余进程；
 * @author: sundx
 * @date: 2020-05-23 23:13:44
 * @Last Modified by: sundx
 * @Last Modified time: 2020-05-24 01:48:15
 */
#include <iostream>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
void outError(const char *);
void dealSig(int);
int main() {
  pid_t pid, sonPid;
  sigset_t blockMask, oldSet;
  // 设置阻塞，防止父进程还注册完回收子进程的函数，子进程已经终止
  sigemptyset(&blockMask);
  sigaddset(&blockMask, SIGCHLD);
  sigprocmask(SIG_BLOCK, &blockMask, &oldSet);
  int i;
  for (i = 0; i < 5; ++i) {
    pid = fork();
    if (pid == 0) {
      std::cout << "child " << i + 1 << " crated and the pid is " << getpid()
                << std::endl;
      break;
    } else if (pid < 0) {
      outError("fork error");
    }
    if (i == 2) {
      sonPid = pid;
    }
  }
  if (i < 5) {
    alarm(2);
    while (1) {
      ;
    }
  } else {
    struct sigaction act, oldAct;
    act.sa_flags = 0;          //注册信号捕捉函数,状态为默认
    sigemptyset(&act.sa_mask); //设置捕捉函数执行期间屏蔽字
    act.sa_handler = dealSig;  //设置回调函数
    sigaction(SIGCHLD, &act, &oldAct);
    sigprocmask(SIG_UNBLOCK, &blockMask, &oldSet); //必须解除对PCB mask的阻塞；
    kill(sonPid, SIGINT);
    while (1) {
      ;
    }
  }
  return 0;
}
void outError(const char *errorMessage) {
  std::cout << errorMessage << std::endl;
  exit(EXIT_FAILURE);
}
void dealSig(int sig) {
  int status;
  pid_t pid;
  while ((pid = waitpid(-1, &status, 0)) != -1) {
    if (WIFSIGNALED(status)) {
      std::cout << "pid: " << pid << " sig is " << WTERMSIG(status)
                << std::endl;
    }
  }
}
